# coding=utf-8
# 全世界最帅的帅哥
from datetime import datetime

from flask import current_app, request
from flask_restful import reqparse
from pydantic import ValidationError
from sqlalchemy.exc import OperationalError, SQLAlchemyError

from ysgg1_club_comment.modules import db
from ysgg1_club_comment.modules.subject_info import SubjectInfo
from ysgg1_club_comment.modules.subject_label import SubjectLabel
from ysgg1_club_comment.modules.subject_mapping import SubjectMapping
from ysgg1_club_comment.modules.subject_radio import SubjectRadio
from ysgg1_club_subject.comment.data_parser.radio_data import RadioData
from ysgg1_club_subject.comment.enums.subject_type_enum import SubjectTypeEnum
from .subject_type_handler import SubjectTypeHandler
from ...subject_serializers.radio_type_serializer import RadioTypeSerializer


# 单选题目的策略类
class RadioTypeHandler(SubjectTypeHandler):

    @staticmethod
    def get_handler_type():
        return SubjectTypeEnum.RADIO

    @classmethod
    def add(cls):
        """
        单选题目的插入
        :return:
        """

        try:
            parser = reqparse.RequestParser()
            parser.add_argument('subjectName', required=True, help="题目名称不能为空")
            parser.add_argument('subjectDifficult', required=True, help="题目难度不能为空")
            parser.add_argument('subjectScore', required=True, help="题目分数不能为空")
            parser.add_argument('subjectParser', required=False)
            parser.add_argument('subjectAnswer', required=True, help="题目答案不能为空")

            args = parser.parse_args()
            subject_name = args.subjectName
            subject_difficult = args.subjectDifficult
            subject_score = args.subjectScore
            subject_parser = args.subjectParser
            subject_answer = args.subjectAnswer

            subject_info = SubjectInfo(
                subject_name=subject_name, subject_difficult=subject_difficult,
                subject_type=cls.get_handler_type().code,
                subject_score=subject_score, subject_parse=subject_parser,
                subject_answer=subject_answer
            )
            db.session.add(subject_info)
            db.session.flush()
            subject_id = subject_info.id

            request_json = request.get_json()
            radio_data = RadioData(subjectCategoryIds=request_json.get('subjectCategoryIds'),
                                   subjectLabelIds=request_json.get('subjectLabelIds'),
                                   optionList=request_json.get('optionList'))

            option_list = radio_data.optionList
            subject_radio_list = []
            for option in option_list:
                option_type, is_correct, option_content = (option["optionType"], option["isCorrect"],
                                                           option["optionContent"])
                subject_radio_list.append(
                    SubjectRadio(subject_id=subject_id,
                                 option_type=option_type,
                                 option_content=option_content,
                                 is_correct=is_correct)
                )
            db.session.add_all(subject_radio_list)

            subject_category_ids = radio_data.subjectCategoryIds
            subject_label_ids = radio_data.subjectLabelIds
            subject_mapping_list = []
            for category_id in subject_category_ids:
                for label_id in subject_label_ids:
                    subject_mapping_list.append(
                        SubjectMapping(subject_id=subject_id, category_id=category_id, label_id=label_id)
                    )

            db.session.add_all(subject_mapping_list)
            db.session.commit()
            es_dict = {"subject_id": subject_id, "subject_answer": subject_answer, "create_time": datetime.now(),
                       "create_user": "ysgg1", "subject_name": subject_name,
                       "subject_type": cls.get_handler_type().code
                       }
            return es_dict

        except (OperationalError, SQLAlchemyError, Exception, ValidationError) as e:
            db.session.rollback()
            current_app.logger.error(f"{e.__str__()}")
            return {"code": 500, "message": f"{e.__str__()}"}

    @staticmethod
    def query(subject_info):

        subject_id = subject_info.id
        subject_radio_list = SubjectRadio.query.filter_by(subject_id=subject_id, is_delete=0).all()

        option_list = []
        for subject_radio in subject_radio_list:
            option_list.append(
                {
                    "option_type": subject_radio.option_type,
                    "option_content": subject_radio.option_content,
                    "is_correct": subject_radio.is_correct
                }
            )

        # 要去重
        label_id_list = SubjectMapping.query.filter_by(subject_id=subject_id, is_delete=0).with_entities(
            SubjectMapping.label_id).all()
        # 涉及到SubjectMapping这张表的内容需要考虑去重
        label_id_set = set(map(lambda subject_mapping: subject_mapping.label_id, label_id_list))
        label_name_list = SubjectLabel.query.with_entities(SubjectLabel.label_name).filter(
            SubjectLabel.id.in_(label_id_set), ~SubjectLabel.is_delete).all()
        label_name_list = list(map(lambda subject_label: subject_label.label_name, label_name_list))
        data = RadioTypeSerializer((subject_info, option_list, label_name_list)).to_dict()
        return {"success": True, "code": 200, "data": data}
